<?php
namespace app\modules\m\controllers;

use app\common\service\ConstantMapService;
use app\common\service\PayOrderService;
use app\common\service\UrlService;
use app\common\service\UtilService;
use app\common\service\weixin\PayApiService;
use app\models\member\OauthMemberBind;
use app\models\pay\PayOrder;
use app\modules\m\controllers\common\BaseController;
use yii\log\FileTarget;

class PayController extends BaseController
{
    public $layout = 'main';
    //购买支付页面
    public function actionBuy()
    {
        $pay_order_id = intval( $this->get("pay_order_id",0) );
        $reback_url = UrlService::buildMUrl("/user/index");

        if( !$pay_order_id ){
            return $this->redirect( $reback_url );
        }
        $pay_order_info = PayOrder::find()->where(['member_id' => $this->current_user['id'],'id' => $pay_order_id,'status' => -8])->one();
        if( !$pay_order_info ){
            return $this->redirect( $reback_url );
        }

        return $this->render('buy',[
            'pay_order_info' => $pay_order_info
        ]);
    }

    public function actionPrepare()
    {
        $pay_order_id = intval( $this->post( "pay_order_id",0 ) );
        if( !$pay_order_id ){
            return $this->renderJson( [],ConstantMapService::$default_syserror,-1 );
        }

        if( !UtilService::isWechat() ){
            return $this->renderJson( [],"仅支持微信支付，请将页面链接粘贴至微信打开",-1 );
        }

        $pay_order_info = PayOrder::find()->where(['member_id' => $this->current_user['id'],'id'=>$pay_order_id,'stauts' => -8])->one();

        if( !$pay_order_info ){
            return $this->renderJson( [],ConstantMapService::$default_syserror,-1 );
        }

        $openid = $this->getOpenId();
        if( !$openid ){
            return $this->renderJson( [],"请先绑定微信再购买~~",-1 );
        }

        $config_weixin = \Yii::$app->params['weixin'];
        $wx_target = new PayApiService( $config_weixin );
        $notify_url = $config_weixin['pay']['notify_url']['m'];
        $wx_target->setParameter('appid',$config_weixin['appid'] );
        $wx_target->setParameter('mch_id',$config_weixin['pay']['mch_id'] );
        $wx_target->setParameter('openid',$openid);
        $wx_target->setParameter('body',$pay_order_info['note']);
        $wx_target->setParameter('out_trade_no',$pay_order_info['order_sn']);
        $wx_target->setParameter('total_fee',$pay_order_info['pay_price'] * 100);
        $wx_target->setParameter('notify_url',UrlService::buildMUrl( $notify_url ));
        $wx_target->setParameter('trade_type',"JSAPI");
        $prepayInfo = $wx_target->getPrepayInfo();
        if( !$prepayInfo ){
            return $this->renderJson( [],"支付失败，请重新支付~~",-1 );
        }
        $wx_target->setPrepayId( $prepayInfo['prepay_id'] );
        return $this->renderJson( $wx_target->getParameters() );
    }

    private function getOpenId(){
        $openid = $this->getCookie( $this->auth_cookie_current_openid,'' );
        if( !$openid ){
            $openid_info = OauthMemberBind::findOne( ['member_id' => $this->current_user['id']] );
            if( !$openid_info || !isset( $openid_info['openid'] ) ){
                return false;
            }
            $openid  = $openid_info['openid'];
        }
        return $openid;
    }

    public function actionCallback(){
        if( !\Yii::$app->request->isPost ){
            return $this->payEcho( false );
        }

        $check_ret = $this->OrderCallbackCheck();
        if( !$check_ret ){
            return $this->payEcho( false );
        }

        $order_sn = $check_ret['order_sn'];
        $pay_order_info = PayOrder::findOne( ['order_sn' => $order_sn] );

        if( !$pay_order_info ){
            return $this->payEcho( false );
        }

        if( ($pay_order_info['pay_price'] * 100) != $check_ret['total_fee'] ){
            return $this->payEcho( false );
        }

        if( $pay_order_info['status'] == 1 ){
            return $this->payEcho( false );
        }

        $params = [
            'pay_sn' =>$check_ret['transaction_id']
        ];
        PayOrderService::orderSuccess( $pay_order_info['id'],$params );
        //记录回调信息
        PayOrderService::setPayOrderCallbackData($pay_order_info['id'],'pay',$check_ret['callback_data']);

        return $this->payEcho( true );



    }

    protected function OrderCallbackCheck(){
        $xml = file_get_contents("php://input");
        $this->recordCallback( $xml );

        $config_weixin = \Yii::$app->params['weixin'];
        $wx_target = new PayApiService( $config_weixin );
        $wx_ret = $wx_target->xmlToArray( $wx_target );
        if( !$wx_ret ){
            return false;
        }

        if( $wx_ret['return_code'] == 'FAIL' || $wx_ret['result_code'] == 'FAIL' ){
            return false;
        }

        if( !isset($wx_ret['sign']) ){
            return false;
        }

        $order_sn = $wx_ret['out_trade_no'];

        foreach( $wx_ret as $_key => $_val ){

            if( in_array( $_key,[ 'sign' ] ) ){
                continue;
            }
            $wx_target->setParameter( $_key,$_val );
        }

        if( $wx_target->checkSign( $wx_ret['sign'] ) ){
            return false;
        }

        return [
            "result_code" => 'SUCCESS',
            'client_type' => 'wechat',
            'order_sn' => $order_sn,
            'total_fee' =>$wx_ret['total_fee'],
            'transaction_id'=>$wx_ret['transaction_id'],
            'openid' =>$wx_ret['openid'],
            'callback_data' =>$xml
        ];
    }

    public function recordCallback( $xml )
    {
        $log = new FileTarget();
        $log->logFile = \Yii::$app->getRuntimePath().'logs/online_pay_'.date("Ymd").'.log';
        $request_uri = isset( $_SERVER['REQUEST_URI'] )?$_SERVER['REQUEST_URI']:'';
        $log->messages[] = [
            "[url:{$request_uri}][xml data:{$xml}]",
            1,
            'application',
            microtime( true )
        ];
        $log->export();
    }

    //pay输出
    public function payEcho( $flag = true,$client_type = "wechat" )
    {
        $return_code = $flag?"SUCCESS":"FAIL";
        $return_msg = $flag?"OK":"FAIL";
        $xml = <<<EOT
    <xml>
    <return_code><![CDATA[{$return_code}]]></return_code>
    <return_msg><![CDATA[{$return_msg}]]></return_msg>
    </xml>
EOT;

    }


}